package com.cheer.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.cheer.common.Page;
import com.cheer.dao.LecCourseDao;
import com.cheer.dao.LecOrgNameCountDTO;
import com.cheer.dao.LecTeacherDao;
import com.cheer.dao.OaAdminDao;
import com.cheer.dto.LecCourseAddDTO;
import com.cheer.entity.LecCourseEntity;
import com.cheer.entity.LecTeacherEntity;
import com.cheer.entity.OaAdminEntity;
import com.cheer.entity.OaLearnClassEntity;
import com.cheer.enums.AdminRoleEnum;
import com.cheer.enums.CheckStatusEnum;
import com.cheer.enums.LectureTypeEnum;
import com.cheer.enums.ResourceEnum;
import com.cheer.exception.ServiceException;
import com.cheer.param.LecCourseListParam;
import com.cheer.security.UserInfoHolder;
import com.cheer.service.LecCourseService;
import com.cheer.service.LecResourceService;
import com.cheer.service.LecTeacherService;
import com.cheer.service.OaLearnClassService;
import com.cheer.util.ExcelsUtil;
import com.cheer.util.FileDownUtil;
import com.cheer.vo.*;
import com.google.common.collect.Lists;
import org.apache.poi.ss.usermodel.CellStyle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.*;

import java.util.stream.Collectors;

@Service("lecCourseService")
public class LecCourseServiceImpl extends ServiceImpl<LecCourseDao, LecCourseEntity> implements LecCourseService {

    private static final Logger log = LoggerFactory.getLogger(LecCourseServiceImpl.class.getName());

    @Autowired
    private LecCourseDao lecCourseDao;

    @Autowired
    private LecTeacherDao lecTeacherDao;

    @Autowired
    private OaLearnClassService oaLearnClassService;

    @Autowired
    private UserInfoHolder userInfoHolder;

    @Autowired
    private LecResourceService lecResourceService;

    @Autowired
    private LecTeacherService lecTeacherService;

    @Autowired
    private OaAdminDao oaAdminDao;


    @Override
    public Page<LecCourseVO> list(LecCourseListParam lecCourseListParam) {

        IPage<LecCourseVO> pageVo;
        // 讲师
        if (userInfoHolder.getAdmin().getRoleId() == 2) {
            LecTeacherEntity teacher = lecTeacherDao.selectByAccount(userInfoHolder.getAdmin().getAdTel());
            if (teacher == null) {
                throw new ServiceException("讲师不存在");
            }
            lecCourseListParam.setTeaId(teacher.getId());
            pageVo = lecCourseDao.listByCoursePage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>( lecCourseListParam.getPageNum(), lecCourseListParam.getPageSize())
                            ,lecCourseListParam);

        } else {
            Integer org = userInfoHolder.getAdmin().getPid();

            String path = null;
            if (org != 0) {
                OaLearnClassEntity learnClass = oaLearnClassService.getById(org);
                if (learnClass == null) {
                    throw new ServiceException("单位不存在");
                }
                path = learnClass.getPath() + org + ",";
            }
            lecCourseListParam.setPath(path);
            lecCourseListParam.setSearchBelong();
            pageVo = lecCourseDao.listByCoursePage(new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>( lecCourseListParam.getPageNum(), lecCourseListParam.getPageSize())
                            ,lecCourseListParam);
        }
        List<String> paths = pageVo.getRecords().stream().map(LecCourseVO::getPath).filter(path -> StrUtil.isNotBlank(path)).collect(Collectors.toList());
        Map<Integer, String> orgIdMapOrgName = lecTeacherService.getOrgIdMapOrgName(paths);

        pageVo.getRecords().forEach( vo -> {
            vo.assembleLectureTime();
            vo.setBelongsStr(LectureTypeEnum.getLectureTypes(vo.getBelong()));
            if(CollectionUtil.isNotEmpty(orgIdMapOrgName)){
                vo.setOrgStr(lecTeacherService.getOrgStr(orgIdMapOrgName, vo.getPath()));
            }
            vo.setModelStr();
        });
        return new Page<>(pageVo, pageVo.getRecords());
    }

    @Override
    public void delete(List<Integer> ids) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        // 检查权限是否足够
        roleCheck(ids);
        lecCourseDao.deleteBatchIds(ids);
    }

    @Override
    public void review(List<Integer> ids, Integer status) {
        if (CollectionUtil.isEmpty(ids)) {
            return;
        }
        Integer id = userInfoHolder.getAdmin().getId();
        OaAdminEntity oaAdminEntity = oaAdminDao.selectById(id);

        if(status == CheckStatusEnum.IS_PASS.getCode() || status == CheckStatusEnum.IS_REFUSE.getCode()){
            if(oaAdminEntity.getRoleId() == AdminRoleEnum.TEACHER.getCode()){
                throw new ServiceException("需管理员端权限修改！");
            }
        }
        LecCourseEntity entity = new LecCourseEntity();
        entity.setStatus(status);

        lecCourseDao.update(entity, new QueryWrapper<LecCourseEntity>().in("id", ids));
    }

    @Override
    public void add(LecCourseAddDTO addDTO) {

        OaAdminEntity admin = oaAdminDao.selectById(userInfoHolder.getAdmin().getId());
        if(ObjectUtil.isNull(admin)){
            throw new ServiceException("当前账户已删除！");
        }
        if(admin.getPid() == OaLearnClassServiceImpl.TOP_LEVEL){
            throw new ServiceException("填写讲座,需先完善组织机构信息!");
        }
        LecTeacherEntity teacher = lecTeacherDao.selectByAccount(admin.getAdTel());
        if (teacher == null) {
            throw new ServiceException("讲师不存在");
        }
        LecCourseEntity entity = new LecCourseEntity();
        BeanUtils.copyProperties(addDTO, entity);
        entity.setTeacherId(teacher.getId());
        entity.setPath(teacher.getPath());
        entity.setImage(CollectionUtil.join(addDTO.getImages(), ","));
        entity.setLectureFile(CollectionUtil.join(addDTO.getLectureFiles(), ","));
        entity.setVitae(CollectionUtil.join(addDTO.getVitaes(), ","));
        entity.setMaterial(CollectionUtil.join(addDTO.getMaterials(), ","));
        entity.setBelong(JSONUtil.parseArray(addDTO.getBelongs()).toString());
        entity.setCourseType(addDTO.getCourseType());

        lecCourseDao.insert(entity);
        //宣讲积分计算
        //根据教师id,将score根据课程类型加分不同分值score=score+5|3|1
        log.debug("+++++ 教师id {}, 此次宣讲类型 {},此次加分值 {}+++++", teacher.getId(), addDTO.getCourseType(), addDTO.getCourseType()==1 ? 5 : addDTO.getCourseType()==2?3:1);
        lecTeacherDao.updateScoreByTeacherId(teacher.getId(), addDTO.getCourseType()==1 ? 5 : addDTO.getCourseType()==2?3:1);

    }



    @Override
    public LecCourseInfoVO info(Integer id) {


        roleCheck(Lists.newArrayList(id));
        LecCourseEntity entity = lecCourseDao.selectById(id);
        LecCourseInfoVO vo = new LecCourseInfoVO();
        BeanUtils.copyProperties(entity, vo);
        vo.setStartTime(DateUtil.format(entity.getStartTime(), DatePattern.NORM_DATETIME_FORMAT));
        vo.setEndTime(DateUtil.format(entity.getEndTime(), DatePattern.NORM_DATETIME_FORMAT));

        List<FileVO> fileVOs = lecResourceService.getFileVOs(entity.getImage(), ResourceEnum.IMAGE);
        vo.setImages(fileVOs);

        List<FileVO> lectureFiles = lecResourceService.getFileVOs(entity.getLectureFile(), ResourceEnum.DOC);
        vo.setLectureFiles(lectureFiles);

        List<FileVO> vitaes = lecResourceService.getFileVOs(entity.getVitae(), ResourceEnum.DOC);
        vo.setVitaes(vitaes);

        List<FileVO> materials = lecResourceService.getFileVOs(entity.getMaterial(), ResourceEnum.OTHER);
        vo.setMaterials(materials);
        if(StrUtil.isNotBlank(entity.getBelong())){
            vo.setBelongs(JSONUtil.toList(entity.getBelong(), List.class));
        }
        //判断entity的courseType是否为空
        if (entity.getCourseType() != null) {
            vo.setCourseType(entity.getCourseType());
        }

        return vo;
    }


    @Override
    public void update(LecCourseAddDTO addDTO) {

        LecCourseEntity entity = lecCourseDao.selectById(addDTO.getId());
        if(entity.getCourseType() != addDTO.getCourseType()){
            //根据宣讲类型减积分
            LecTeacherEntity teacher = lecTeacherDao.selectById(entity.getTeacherId());
            log.info("+++++ 教师id {}, 此次宣讲类型 {},此次减分值 {}+++++", teacher.getId(), entity.getCourseType(), entity.getCourseType()==1 ? 5 : entity.getCourseType()==2?3:1);
            lecTeacherDao.updateScoreByTeacherId(teacher.getId(), entity.getCourseType()==1 ? -5 : entity.getCourseType()==2?-3:-1);
            //根据宣讲类型加积分
            log.info("+++++ 教师id {}, 此次宣讲类型 {},此次加分值 {}+++++", teacher.getId(), addDTO.getCourseType(), addDTO.getCourseType()==1 ? 5 : addDTO.getCourseType()==2?3:1);
            lecTeacherDao.updateScoreByTeacherId(teacher.getId(), addDTO.getCourseType()==1 ? 5 : addDTO.getCourseType()==2?3:1);
        }

        roleCheck(Lists.newArrayList(addDTO.getId()));
        LecCourseEntity update = new LecCourseEntity();
        BeanUtils.copyProperties(addDTO, update);
        update.setImage(CollectionUtil.join(addDTO.getImages(), ","));
        update.setLectureFile(CollectionUtil.join(addDTO.getLectureFiles(), ","));
        update.setVitae(CollectionUtil.join(addDTO.getVitaes(), ","));
        update.setMaterial(CollectionUtil.join(addDTO.getMaterials(), ","));
        update.setBelong(JSONUtil.parseArray(addDTO.getBelongs()).toString());

        lecCourseDao.updateById(update);



    }

    @Override
    public void download(LecCourseListParam lecCourseListParam) {
        String path = null;
        Integer org = lecCourseListParam.getOrg();
        if (org != 0) {
            OaLearnClassEntity learnClass = oaLearnClassService.getById(org);
            if (learnClass == null) {
                throw new ServiceException("单位不存在");
            }
            path = learnClass.getPath() + org + ",";
        }
        lecCourseListParam.setPath(path);
        lecCourseListParam.setSearchBelong();
        List<LecCourseEntity> list = lecCourseDao.listByCourse(lecCourseListParam);
        // 创建讲座附加文件
        String workDir = createTempFolder(list);
        // 打包文件下载
        File zip = ZipUtil.zip(workDir);
        log.info("======文件输入地址====={}", workDir);
        // 返回下载
        FileDownUtil.downTemporaryFile(workDir, zip, "讲座信息.zip");
    }

    /**
     * 创建临时文件夹
     * @param list
     * @return
     */
    @Override
    public String createTempFolder(List<LecCourseEntity> list) {

        String workDir = lecResourceService.getTempLecFile(list);
        createExcelToTargetPath(list, workDir);
        return workDir;
    }

    /**
     * 创建excel表格到
     * @param list
     * @param workDir
     */
    private void createExcelToTargetPath(List<LecCourseEntity> list, String workDir) {

        List<LecCourseExportVO> lecCourseExportVOS = new ArrayList<>();
        List<LecCourseTeaExportVO> lecCourseTeaExportVOS = new ArrayList<>();

        // 1. 查询课程信息和讲师信息
        if(CollectionUtil.isNotEmpty(list)){

            List<Integer> teacherIds = list.stream().map(lecCourse -> lecCourse.getTeacherId()).collect(Collectors.toList());
            Date date = new Date();
            List<LecTeacherEntity> lecTeacherEntities = lecTeacherDao.selectBatchIds(teacherIds);
            log.error("第三个sql耗时"+(date.getTime()-System.currentTimeMillis()));
            Map<Integer, List<LecTeacherEntity>> idMapLecTeacherEntitys = lecTeacherEntities.stream().collect(Collectors.groupingBy(LecTeacherEntity::getId));
            // 讲座信息
            lecCourseExportVOS = LecCourseExportVO.convertTOLecCourseExportVO(idMapLecTeacherEntitys, list);
            // 教师信息
            lecCourseTeaExportVOS = LecCourseTeaExportVO.convertTOLecCourseTeaExportVO(idMapLecTeacherEntitys, list);
        }else{
            lecCourseExportVOS.add(new LecCourseExportVO());
            lecCourseTeaExportVOS.add(new LecCourseTeaExportVO());
        }

        // 将信息写入到excel表中
        //初始化时定义表名
        ExcelWriter writer = ExcelUtil.getWriter(workDir + File.separator + "讲座表.xlsx", "讲座信息");
        writer.setHeaderAlias(LecCourseExportVO.headerAlias);
        CellStyle headCellStyleSheet1 = writer.getHeadCellStyle();
        ExcelsUtil.setCommonHeader(headCellStyleSheet1);
        writer.write(lecCourseExportVOS, true);

        writer.setSheet("教师信息");
        writer.setHeaderAlias(LecCourseTeaExportVO.headerAlias);
        CellStyle headCellStyleSheet2 = writer.getHeadCellStyle();
        ExcelsUtil.setCommonHeader(headCellStyleSheet2);
        writer.write(lecCourseTeaExportVOS, true);

        writer.close();
    }

    @Override
    public int countByStatus(CheckStatusEnum checkStatusEnum, String path) {

        int count = lecCourseDao.countByStatus(checkStatusEnum.getCode(), path);
        return count;
    }

    @Override
    public LecIndexOrgVO getStatisticsOrg(String year, String org) {

        Integer intOrg = Integer.valueOf(org);
        List<SimpleObjectVO> sub = oaLearnClassService.sub(intOrg);
        if(CollectionUtil.isEmpty(sub)){
            return LecIndexOrgVO.createEmptyLecIndex();
        }
        List<Long> orgIds = sub.stream().map(SimpleObjectVO::getId).collect(Collectors.toList());
        List<OaLearnClassEntity> oaLearnClassEntities = (List<OaLearnClassEntity>) oaLearnClassService.listByIds(orgIds);
        List<LecOrgNameCountDTO> lecOrgNameCountDTOS = Lists.newArrayList();


        for (int i = 0; i < oaLearnClassEntities.size(); i++) {

            OaLearnClassEntity oaLearnClassEntity = oaLearnClassEntities.get(i);
            String orgPath = oaLearnClassEntity.getPath() + oaLearnClassEntity.getId() +",";
            LecOrgNameCountDTO lecOrgNameCountDTO = new LecOrgNameCountDTO();
            Integer orgCount = 0;
            orgCount = lecCourseDao.getStatisticsOrg(year, orgPath);
            lecOrgNameCountDTO.setOrgName(oaLearnClassEntity.getName());
            lecOrgNameCountDTO.setLecOrgCount(orgCount);
            lecOrgNameCountDTOS.add(lecOrgNameCountDTO);
        }

        // 排序
        Comparator<LecOrgNameCountDTO> comparable = Comparator.comparing(LecOrgNameCountDTO::getLecOrgCount);
        lecOrgNameCountDTOS.sort(comparable);

        // 抽取
        List<String> orgNameArray = Lists.newArrayList();
        List<Integer> letCountArray = Lists.newArrayList();
        for (int i = 0; i < lecOrgNameCountDTOS.size(); i++) {

            LecOrgNameCountDTO lecOrgNameCountDTO = lecOrgNameCountDTOS.get(i);
            Integer lecOrgCount = lecOrgNameCountDTO.getLecOrgCount();
            String orgName = lecOrgNameCountDTO.getOrgName();
            orgNameArray.add(orgName);
            letCountArray.add(lecOrgCount);
        }

        LecIndexOrgVO lecIndexOrgVO = new LecIndexOrgVO();
        lecIndexOrgVO.setOrgNameArray(orgNameArray);
        lecIndexOrgVO.setLetCountArray(letCountArray);

        return lecIndexOrgVO;
    }

    @Override
    public int countByPath(String path) {

        return lecCourseDao.countByPath(path);
    }

    /**
     * 检查当前账号然后去操作讲座
     * 讲座ID集合
     */
    public void roleCheck(List<Integer> ids){

        // 获取当前登录用户信息
        OaAdminEntity admin = userInfoHolder.getAdmin();
        if(admin == null){
            throw new ServiceException("当前用户未登录！");
        }
        List<Integer> abOptIds = null;
        if(AdminRoleEnum.TEACHER.getCode().equals(admin.getRoleId())) {
            // 获取当前的账号
            LecTeacherEntity lecTeacherEntity = lecTeacherService.getByAccount(admin.getAdTel());
            // 查询当前讲师下面的所有讲座
            QueryWrapper<LecCourseEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .eq(LecCourseEntity::getTeacherId, lecTeacherEntity.getId());
            List<LecCourseEntity> list = list(queryWrapper);
            abOptIds = list.stream().map(LecCourseEntity::getId).collect(Collectors.toList());
        }else{
            // 查询当前管理人下面的所有讲座
            Integer pid = admin.getPid();
            // 最高权限账号不需要校验
            if(pid == 0){
                return;
            }
            OaLearnClassEntity oaLearnClass = oaLearnClassService.getById(pid);
            QueryWrapper<LecCourseEntity> queryWrapper = new QueryWrapper<>();
            queryWrapper.lambda()
                    .likeRight(LecCourseEntity::getPath,oaLearnClass.getPath() + oaLearnClass.getId());
            List<LecCourseEntity> list = list(queryWrapper);
            abOptIds = list.stream().map(LecCourseEntity::getId).collect(Collectors.toList());
        }

        if(CollectionUtil.isEmpty(abOptIds)){
            throw new ServiceException("当前用户无权限操作讲座！");
        }
        // 比较一个集合中是否包含另一个集合
        Set<Integer> ableOptSet = new HashSet<>(abOptIds);
        Set<Integer> optSet = new HashSet<>(ids);

        if(ableOptSet.containsAll(optSet) == false){
            throw new ServiceException("存在无操作权限账号，请重新勾选");
        }
    }

}